/* Copyright 2001,2002,2003 NAH6 BV
 * All Rights Reserved
 *
 *  $Header: /var/lib/cvs/secphone/ui/KeyExchange/DiffieHellmanHandler.h,v 1.7 2003/11/21 12:39:24 itsme Exp $
 *
 *
 */


#ifndef __DIFFIEHELLMANHANDLER_H__

#include "userdatahandler.h"

#include "nhThread.h"
#include "bignum.h"

#include <vector>
#include "vectorutils.h"

#include "dhCalcRequest.h"
#include "dhCalcThread.h"
#include "cryptoVerifier.h"

class CCPhoneDlg;
/*
#define UDCLT_DIFFIEHELLMAN 0

#define DHMSG_START     UDMSG(UDCLT_DIFFIEHELLMAN, 1)
#define DHMSG_CONTINUE  UDMSG(UDCLT_DIFFIEHELLMAN, 2)
#define DHMSG_END       UDMSG(UDCLT_DIFFIEHELLMAN, 3)
#define DHMSG_REJECT    UDMSG(UDCLT_DIFFIEHELLMAN, 4)
#define DHMSG_CONFIRM   UDMSG(UDCLT_DIFFIEHELLMAN, 5)
*/
// these are the pads used to create the specific target usages of
// the shared secret
#define ZZ_AESKEY_PAD 0
#define ZZ_TWOFISHKEY_PAD 1
#define ZZ_KEYSIG_PAD 2

// how many digits of the key-sig hash are displayed
#define KEYSIG_LENGTH 6

enum {
    EV_PKCALC_OK=0,     // set by calcthread, reset before new calc
    EV_PKCALC_FAIL,     // set by calcthread, reset before new calc
    EV_ZZCALC_OK,       // set by calcthread, reset before new calc
    EV_ZZCALC_FAIL,     // set by calcthread, reset before new calc
    EV_SGVERIFY_OK,     // set by calcthread, reset before new calc
    EV_SGVERIFY_FAIL,   // set by calcthread, reset before new calc
    EV_RCV_START,       // set by dh-userdata handler, reset before each wait.
    EV_RCV_END,         // set by dh-userdata handler, reset before each wait.
    EV_RCV_CONTINUE,    // set by dh-userdata handler, reset before each wait.
    EV_RCV_CONFIRM,     // set by dh-userdata handler, reset before each wait.
    EV_RCV_REJECT,      // set by dh-userdata handler, reset before each wait.
    EV_SYNCLOSS,        // pulsed by spipc-handler
    EV_USERREQUEST,     // set by HandleUserStartRequest function, reset after wait
    EV_USERABORT,       // pulsed by phone-handler
    NR_OF_EVENTS,
};


//todo: not all of these public methods should be public
class DiffieHellmanHandler : public NHThread, public UDClientHandler {
public:
    DiffieHellmanHandler(CCPhoneDlg& dlg);
    virtual ~DiffieHellmanHandler();

    void SetHighCalcPriority();
    void SetLowCalcPriority();

    // actions
    void Hangup();
    bool StartPubPrivKeyCalc();
    bool StartSharedSecretCalc();
//    bool StartVerifySubgroupCalc();

    bool isVersionOk();
    bool isVersionTooNew();
    bool isVersionTooOld();

    void SendStartMessage();
    void SendContinueMessage();
    void SendEndMessage();
    void SendRejectMessage();
    void SendConfirmMessage();

    virtual bool StopSending(); // from udchandler

    bool VerifyHash();
    void SetNewKey();

    // utility
    int WaitState(DWORD eventMask);
    void ClearState();

    // core protocol functions
    void mainDiffieHellmanThread();
    bool BeBop(int recursionlevel= 0);
    bool BeAlice(int recursionlevel= 0);

    bool WaitForPubPrivKeyCalc();
    bool WaitForSubgroupCalc();
    bool WaitForNewKeyExchange();
    bool WaitForHangup();
    bool WaitForEndMessage();
    bool WaitForSharedSecret();
    int WaitForContinueOrReversal();
    bool WaitForSyncLoss();

    // determined by current 'wait'
    bool mayReceiveConfirmMessage();
    bool mayReceiveEndMessage();
    bool mayReceiveContinueMessage();
    bool mayReceiveStartMessage();

    // called externally
    virtual bool HandleUserdataMessage(const ByteVector& data);

    // protocol message handlers
    bool HandleStartMessage(int version, const ByteVector& publichash);
    bool HandleContinueMessage(const Number &publicvalue);
    bool HandleEndMessage(const Number &publicvalue);
    bool HandleConfirmMessage(const ByteVector &nonce);
    bool HandleRejectMessage();

    // other event handlers
    bool HandleSyncLoss();
    bool HandleSyncFound();
    bool HandleUserAbort();
    void HandleUserStartRequest();

    void ResetReceiveEvents();

    virtual void StartThread(); // fron nhThread

protected:
    virtual DWORD ThreadProc();
    virtual const char* name() const { return "DiffieHellmanHandler"; }

//private:  !!! uncomment this
public:

    HANDLE m_hEvents[NR_OF_EVENTS];

    DWORD m_dwValidityFlags;
    DWORD m_dwCurrentWait;

    const Number m_modulus_prime;       // 'p'
    const Number m_subgroup_prime;      // 'q'
    const Number m_subgroup_generator;  // 'g'

    Number m_my_secret;
    Number m_my_public;     // = g ^ my_secret mod p

    Number m_other_public;  // = g ^ other_secret mod p
    Number m_shared_secret; // = other_public^my_secret mod p

    ByteVector m_other_nonce;       // from confirm message

    /*const */ int m_my_version;    //!! todo uncomment const
    int m_other_version;

    int m_negotiated_version;

    bool m_bIAmTheOriginator;
    bool m_bInSync;

    ByteVector m_other_public_hash;

    CalcRequestQueue m_calcrequests;

    CalcThread m_calc;

    CryptoVerifier m_verifier;

    CCPhoneDlg& m_dlg;

    CRITICAL_SECTION m_lock;    // protects access to m_dwValidityFlags
};

#define __DIFFIEHELLMANHANDLER_H__
#endif
